home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 526-550 / disk_547 / mmbshift / mmbshift.asm < prev    next >
Assembly Source File  |  1992-05-06  |  13KB  |  477 lines

  1.  
  2. *    MMBShift
  3. *    By Preben Nielsen
  4. *
  5. *    This small program makes the middle button (on a three-button mouse)
  6. *       act as a shift key. This means that it will be very easy to select
  7. *       multiple icons on the workbench without having to press a Shift-Key.
  8. *
  9. *    Once installed, the program only uses 166 bytes of memory.
  10. *    To get back to normal simply run the program again.
  11. *
  12. *    NOTE:    There's no need to 'RUN' or 'RUNBACK' this program from the
  13. *        CLI. It terminates immediately.
  14. *
  15. *HISTORY
  16. *          Made with Hisoft V2.12
  17. *
  18. *  V1.0   01-Sep-91: First attempt. Works of course.
  19.  
  20.  
  21.     OPT O+
  22.     OPT O1+            ; Tells when a branch could be optimised to short
  23.     OPT i+            ; Tells when '#' is probably missing
  24.  
  25.         incdir        "AsmInc:"
  26.         include        "P.i"
  27.         include        "relMacros.i"
  28.         include        "exec/exec_lib.i"
  29.         include        "exec/io.i"
  30.         include        "exec/memory.i"
  31.         include        "exec/interrupts.i"
  32.         include        "devices/input.i"
  33.         include        "devices/inputevent.i"
  34.         include        "libraries/dosextens.i"
  35.         include        "libraries/dos_lib.i"
  36.  
  37. DB        EQUR        A4
  38.  dcDeclare    A4
  39.  dcAPtr        PProcess
  40.  dcAPtr        WBMsg
  41.  dcAPtr        DosBase
  42.  dcAPtr        HMem
  43.  dcEnd
  44.  
  45. Start        dcAlloc                    ; Allocate memory for variables
  46.         dcReset                    ; Clear the memory
  47.         Prepare        Exec_Call
  48.         suba.l        A1,A1
  49.         CallLib        FindTask        ; Find us
  50.         move.l        D0,PProcess(DB)
  51.         movea.l        D0,A2
  52.         tst.l        pr_CLI(A2)
  53.         bne.S        GetLibs
  54. WBStart        lea        pr_MsgPort(A2),A0
  55.         CallLib        WaitPort        ; wait for a message
  56.         lea        pr_MsgPort(A2),A0
  57.         CallLib        GetMsg            ; then get it
  58.         move.l        D0,WBMsg(DB)        ; save it for later reply
  59. GetLibs        lea        DosName(PC),A1
  60.         CallLib        OldOpenLibrary
  61.         move.l        D0,DosBase(DB)
  62.         beq.S        Error
  63.         lea        IHSName(PC),A1
  64.         Call        FindThisPort
  65.         beq.S        DoInstall
  66. DoRemove    moveq        #REMOVED,D7
  67.         lea        IHS(PC),A0
  68.         lea        PSEndIHS1(PC),A1
  69.         lea        PSEndIHS2(PC),A2
  70.         Call        RemoveHandler
  71.         beq.S        ShowMsg
  72.         moveq        #CANTREMOVE,D7
  73.         bra.S        ShowMsg
  74. DoInstall    moveq        #INSTALLED,D7
  75.         lea        IHS(PC),A0
  76.         lea        PSPrepIHS1(PC),A1
  77.         lea        PSPrepIHS2(PC),A2
  78.         Call        InstallHandler
  79.         beq.S        ShowMsg
  80.         moveq        #CANTINSTALL,D7
  81. ShowMsg        move.l        D7,D0
  82.         Call        CONMsg
  83.  
  84. Error
  85. Exit        Prepare        Exec_Call
  86. FreeDos        move.l        DosBase(DB),D0
  87.         beq.S        ReplyWB
  88.         move.l        D0,A1
  89.         CallLib        CloseLibrary
  90. ReplyWB        move.l        WBMsg(DB),D2
  91.         beq.S        AllDone
  92.         CallLib        Forbid            ; We were started from WB
  93.         movea.l        D2,A1
  94.         CallLib        ReplyMsg        ; Reply WBMessage
  95. AllDone        dcFree
  96.         moveq        #0,D0
  97.         rts
  98.  
  99. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  100. *»»» Console message routines »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  101. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  102. FHandle        EQUR        D5
  103. *»»» Call:    D0 = Msg-number
  104. *»»» Writes a general copyright message and then a more specific message.
  105. *»»» Writes to standard output when run from CLI, and opens its own window
  106. *»»» when run from Workbench.
  107. CONMsg        Push        D0-D7/A0-A6
  108.         Prepare        Dos_Call
  109.         move.l        D0,D4
  110.         moveq        #0,D6
  111.         CallLib        Output
  112.         move.l        D0,FHandle
  113.         bne.S        1$
  114.         moveq        #1,D6
  115.         lea        CONName(PC),A0
  116.         move.l        A0,D1
  117.         move.l        #MODE_OLDFILE,D2
  118.         CallLib        Open
  119.         move.l        D0,FHandle
  120.         beq.S        2$
  121. 1$        moveq        #INFOMSG,D0
  122.         Call        SendMsg
  123.         move.l        D4,D0
  124.         Call        SendMsg
  125.         tst.l        D6
  126.         beq.S        2$
  127.         moveq        #127,D1
  128.         CallLib        Delay
  129.         move.l        FHandle,D1
  130.         CallLib        Close
  131. 2$        Pop        D0-D7/A0-A6
  132.         rts
  133.  
  134. *»»» Call:    D0 = Msg-number
  135. SendMsg        neg.l        D0
  136.         lsl.l        #1,D0
  137.         lea        CONMsgTable(PC),A0
  138.         add.w        0(A0,D0),A0
  139.         move.l        A0,D2
  140.         moveq        #-1,D3
  141. 1$        addq.l        #1,D3
  142.         tst.b        (A0)+
  143.         bne.S        1$
  144.         move.l        FHandle,D1
  145.         Prepare        Dos_Call
  146.         CallLib        Write
  147.         rts
  148.  
  149. INFOMSG        =0
  150. INSTALLED    =-1
  151. REMOVED        =-2
  152. CANTINSTALL    =-3
  153. CANTREMOVE    =-4
  154.  
  155. CONText        MACRO
  156.         dc.w        \1-CONMsgTable
  157.         ENDM
  158. CONMsgTable    CONText        Msg
  159.         CONText        Msg1
  160.         CONText        Msg2
  161.         CONText        Msg3
  162.         CONText        Msg4
  163.  
  164. CONName        dc.b        'CON:100/60/330/63/MMBShift',0
  165. Msg        dc.b        10,$9B,'0;33m MMBShift V1.0',10
  166.         dc.b        $9B,'0;31m 1991 by ',$9B,'0;33mPreben Nielsen',$9B,'0;31m',10,' ',0
  167. Msg1        dc.b        'has now been installed...',10,0
  168. Msg2        dc.b        'has now been removed...',10,0
  169. Msg3        dc.b        "Error: Can't install handler",10,0
  170. Msg4        dc.b        "Error: Can't remove handler",10,0
  171.         EVEN
  172. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  173. *»»» End of Console message routines »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  174. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  175.  
  176. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  177. *»»» Inputhandler removal and installation routines »»»»»»»»»»»»»»»»»»»»»»»»
  178. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  179. rtsValue    EQUR        D7
  180. *»»» This is general-purpose inputhandler removal-routine
  181. *»»» It only needs an ihs with a port-name to remove the handler
  182. *»»» Call:    A0 = ihs
  183. *»»»        A1 = first ihs-installation-routine or NULL
  184. *»»»        A2 = second ihs-installation-routine or NULL
  185. *»»» Return:    D0 = 0 means succes
  186. RemoveHandler    Push        D1/rtsValue/A0-A3/A6
  187.         moveq        #-1,rtsValue
  188.         move.l        A2,A3
  189.         move.l        A0,A2
  190.         move.l        A1,D1
  191.         beq.S        1$
  192.         jsr        (A1)        ; A0 = ihs
  193.         beq.S        2$
  194.         move.l        D0,A2
  195. 1$        move.l        A2,A0
  196.         Prepare        Exec_Call
  197.         moveq        #IND_REMHANDLER,D0
  198.         Call        TellInputDevice
  199.         move.l        D0,rtsValue
  200.         bne.S        2$
  201.         lea        ihs_Port(A2),A1
  202.         CallLib        RemPort
  203.         moveq        #0,D0
  204.         bra.S        3$
  205. 2$        moveq        #-1,D0
  206. 3$        move.l        A3,D1
  207.         beq.S        4$
  208.         move.l        A2,A0
  209.         jsr        (A3)        ; A0 = ihs, D0 = 0 means succes
  210. 4$        move.l        rtsValue,D0
  211.         Pop        D1/rtsValue/A0-A3/A6
  212.         rts
  213.  
  214. *»»» This is general-purpose inputhandler installation-routine
  215. *»»» It only needs an ihs with a port-name to install the handler
  216. *»»» Call:    A0 = ihs
  217. *»»»        A1 = first ihs-installation-routine or NULL
  218. *»»»        A2 = second ihs-installation-routine or NULL
  219. *»»» Return:    D0 = 0 means succes
  220. InstallHandler    Push        D1/rtsValue/A0-A3/A6
  221.         moveq        #-1,rtsValue
  222.         move.l        A2,A3
  223.         move.l        A0,A2
  224.         move.l        A1,D1
  225.         beq.S        1$
  226.         jsr        (A1)        ; A0 = ihs
  227.         beq.S        2$
  228.         move.l        D0,A2
  229. 1$        move.l        A2,A0
  230.         moveq        #IND_ADDHANDLER,D0
  231.         Call        TellInputDevice
  232.         move.l        D0,rtsValue
  233.         bne.S        2$
  234.         lea        ihs_Port(A2),A1
  235.         move.l        ihs_PortName(A2),MP+LN_NAME(A1)    ;MsgPort->mp_Node.ln_Name=Name;
  236.         clr.b        MP+LN_PRI(A1)            ;MsgPort->mp_Node.ln_Pri =0;
  237.         move.b        #NT_MSGPORT,MP+LN_TYPE(A1)    ;MsgPort->mp_Node.ln_Type=NT_MSGPORT;
  238.         move.b        #PA_IGNORE,MP_FLAGS(A1)        ;MsgPort->mp_Flags     =PA_IGNORE;
  239.         Prepare        Exec_Call
  240.         CallLib        AddPort
  241.         moveq        #0,D0
  242.         bra.S        3$
  243. 2$        moveq        #-1,D0
  244. 3$        move.l        A3,D1
  245.         beq.S        4$
  246.         move.l        A2,A0
  247.         jsr        (A3)        ; A0 = ihs, D0 = 0 means succes
  248. 4$        move.l        rtsValue,D0
  249.         Pop        D1/rtsValue/A0-A3/A6
  250.         rts
  251.  
  252. *»»» Open the input device. Set up the I/O block to add or remove the
  253. *»»» input handler, and send the request to the input device. Finally,
  254. *»»» close the device
  255. *»»» Call:    A0 = ihs
  256. *»»»        D0 = Function to perform (IND_ADDHANDLER/IND_REMHANDLER)
  257. *»»» Return:    D0 = 0 means succes
  258.  dcDeclare    A5
  259.  dcArea        IReq,IOSTD_SIZE
  260.  dcArea        IPort,MP_SIZE
  261.  dcEnd
  262. TellInputDevice    dcAlloc
  263.         dcReset
  264.         Push        D1-D2/rtsValue/A0-A3/A6
  265.         Prepare        Exec_Call
  266.         moveq        #-1,rtsValue
  267.         move.l        D0,D2
  268.         move.l        A0,A2
  269.         lea        IPort(A5),A3
  270.         move.b        #NT_MSGPORT,MP+LN_TYPE(A3)    ; mp_Node.ln_Type=NT_MSGPORT;
  271.         move.b        #PA_SIGNAL,MP_FLAGS(A3)        ; mp_Flags    =PA_SIGNAL;
  272.         moveq        #-1,D0
  273.         CallLib        AllocSignal
  274.         move.b        D0,MP_SIGBIT(A3)        ; mp_SigBit    =MPSigBit;
  275.         bmi.S        2$
  276.         suba.l        A1,A1
  277.         CallLib        FindTask
  278.         move.l        D0,MP_SIGTASK(A3)        ; mp_SigTask     =FindTask(0);
  279.         lea        MP_MSGLIST(A3),A0
  280.         NEWLIST        A0
  281.         lea        IReq(A5),A1
  282.         move.l        A3,IO+MN_REPLYPORT(A1)        ; ExtReq->io_Message.mn_ReplyPort   =taskReplyPort;
  283.         move.b        #NT_MESSAGE,IO+MN+LN_TYPE(A1)    ; ExtReq->io_Message.mn_Node.ln_Type=NT_MESSAGE;
  284.         lea        InputName(PC),A0        ; input.device
  285.         moveq        #0,D0                ; unit#
  286.         moveq        #0,D1                ; flags
  287.         CallLib        OpenDevice
  288.         tst.w        D0                ; flag: error if > 0
  289.         bne.S        1$
  290.         lea        IReq(A5),A1
  291.         move.w        D2,IO_COMMAND(A1)
  292.         lea        ihs_Interrupt(A2),A0
  293.         move.l        A0,IO_DATA(A1)
  294.         CallLib        DoIO
  295.         move.l        D0,rtsValue
  296.         lea        IReq(A5),A1
  297.         CallLib        CloseDevice
  298. 1$        move.b        MP_SIGBIT(A3),D0
  299.         CallLib        FreeSignal
  300. 2$        move.l        rtsValue,D0
  301.         Pop        D1-D2/rtsValue/A0-A3/A6
  302.         dcFree
  303.         rts
  304.  
  305. *»»» Each handler should have such a pair of installation-routines.
  306. *»»» The first one is passed to InstallHandler in A1, and it
  307. *»»» is called immediately when entering InstallHandler.
  308. *»»» The second one is passed to InstallHandler in A2, and it
  309. *»»» is called if installation of handler and message-port succeeds.
  310. *»»» -----------------------------------------------------------------
  311. *»»» Call:    A0 = ihs
  312. *»»» Return:    D0 has to point to ihs to be used when installation proceeds.
  313. *»»»        If D0 = 0 then installation is aborted.
  314. PSPrepIHS1    Push        D1/A0-A1/A6
  315.         Prepare        Exec_Call
  316.         move.l        #HandlerSize,D0
  317.         move.l        #MEMF_PUBLIC|MEMF_CLEAR,D1
  318.         CallLib        AllocMem
  319.         move.l        D0,HMem(DB)
  320.         beq.S        2$
  321.         move.l        D0,A1
  322.         lea        IHS(PC),A0
  323.         move.l        #HandlerSize,D0
  324.         Push        D0/A0-A1
  325.         CallLib        CopyMem
  326.         Pop        D0/A0-A1
  327.         move.l        D0,ihs_Length(A1)        ; This will enable removal by other programs
  328.         lea        HandlerCode-IHS(A1),A0
  329.         move.l        A0,ihs_Interrupt+IS_CODE(A1)    ; ihs_Interrupt.is_Code = Handler
  330.         clr.l        ihs_Interrupt+IS_DATA(A1)    ; ihs_Interrupt.is_Data = 0
  331.         lea        IHSName-IHS(A1),A0
  332.         move.l        A0,ihs_PortName(A1)        ; ihs_PortName          = IHSName
  333.         move.b        #HPRI,ihs_Interrupt+LN_PRI(A1)    ; ihs_Interrupt.is_Node.ln_Pri = HPRI
  334.         move.l        A1,D0
  335. 2$        Pop        D1/A0-A1/A6
  336.         rts
  337. *»»» Call:    A0 = ihs
  338. *»»»        D0 = 0 means everything went perfect
  339. *»»»        -1 means something went wrong during installation
  340. PSPrepIHS2    Push        D0-D1/A0-A1/A6
  341.         tst.l        D0
  342.         beq.S        1$
  343.         move.l        HMem(DB),D0
  344.         beq.S        1$
  345.         move.l        D0,A1
  346.         move.l        #HandlerSize,D0
  347.         Prepare        Exec_Call
  348.         CallLib        FreeMem
  349. 1$        Pop        D0-D1/A0-A1/A6
  350.         rts
  351.  
  352. *»»» Each handler should have such a pair of ending-routines.
  353. *»»» The first one is passed to RemoveHandler in A1, and it
  354. *»»» is called immediately when entering RemoveHandler.
  355. *»»» The second one is passed to RemoveHandler in A2, and it
  356. *»»» is called if removal of handler and message-port succeeds.
  357. *»»» -----------------------------------------------------------------
  358. *»»» Call:    A0 = ihs
  359. *»»» Return:    D0 has to point to ihs to be used when removal proceeds
  360. *»»»        If D0 = 0 then removal is aborted
  361. PSEndIHS1    Push        A1
  362.         lea        IHSName(PC),A1
  363.         Call        FindThisPort
  364.         Pop        A1
  365.         rts
  366. *»»» Call:    A0 = ihs
  367. *»»»        D0 = 0 means everything went perfect
  368. *»»»        -1 means something went wrong during removal
  369. PSEndIHS2    Push        D0-D1/A0-A1/A6
  370.         tst.l        D0
  371.         bmi.S        1$
  372.         Prepare        Exec_Call
  373.         move.l        ihs_Length(A0),D0
  374.         move.l        A0,A1
  375.         CallLib        FreeMem
  376. 1$        Pop        D0-D1/A0-A1/A6
  377.         rts
  378.  
  379. *»»» Call:    A1 = Portname
  380. *»»» Return:    D0 = Port or NULL (cc reflects result also)
  381. FindThisPort    Push        D1-D2/A0-A1/A6
  382.         Prepare        Exec_Call
  383.         move.l        A1,D2
  384.         CallLib        Forbid
  385.         move.l        D2,A1
  386.         CallLib        FindPort
  387.         move.l        D0,D2
  388.         CallLib        Permit
  389.         move.l        D2,D0
  390.         Pop        D1-D2/A0-A1/A6
  391.         rts
  392.  
  393. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  394. *»»» Input-handler start »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  395. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  396. ihs_Port    =0
  397. ihs_Interrupt    =MP_SIZE
  398. ihs_ID        =MP_SIZE+IS_SIZE
  399. ihs_Length    =MP_SIZE+IS_SIZE+4
  400. ihs_Flags    =MP_SIZE+IS_SIZE+8
  401. ihs_PortName    =MP_SIZE+IS_SIZE+10
  402. ihs_LocalArea    =MP_SIZE+IS_SIZE+14
  403. ihs_SIZE    =MP_SIZE+IS_SIZE+14
  404.  
  405. ihs_Start    MACRO
  406.         dcb.b        MP_SIZE        ; Message-Port structure
  407.         dcb.b        IS_SIZE        ; Interrupt structure
  408.         dc.l        'P_IH'        ; ID
  409.         dc.l        0        ; Length of handler 
  410.         dc.w        0        ; Flags
  411.         dc.l        0
  412.         ENDM
  413.  
  414. HPRI        =55
  415. HDisabled    =0
  416. HNoExtRemoval    =1
  417.  
  418. *»»» This is the handler-block
  419. IHS        ihs_Start
  420. *»»» Put local data here
  421. Shifted        dc.w        0
  422. *»»» IHS name
  423. IHSName        dc.b        'MMBShift V1.0 Port',0
  424.         EVEN
  425. *»»» For each event in the event list:
  426. *»»»  If we were waiting for this event then signal the task.
  427. *»»» When all the events have been checked, return the event list so that
  428. *»»» others can do their things.
  429. EList        EQUR    A0
  430. Event        EQUR    A1
  431.  
  432. Next        =ie_NextEvent
  433. Class        =ie_Class
  434. Code        =ie_Code
  435. Qual        =ie_Qualifier
  436.  
  437. * Call:  A0 = List of InputEvents, A1 = HandlerData
  438. HandlerCode    Push        Event/EList/A2
  439.         move.l        EList,Event
  440. ieLoop        move.l        Event,D0
  441.         beq.S        NoMoreEvents
  442.         cmpi.b        #IECLASS_RAWMOUSE,Class(Event)
  443.         bne.S        DontRemove
  444.         cmpi.w        #IECODE_MBUTTON,Code(Event)
  445.         beq.S        PressMMB
  446.         cmpi.w        #IECODE_UP_PREFIX|IECODE_MBUTTON,Code(Event)
  447.         bne.S        DontRemove
  448. ReleaseMMB    moveq        #0,D0
  449.         bra.S        ChangeStatus
  450. PressMMB    clr.w        Class(Event)            ; Remove the event (make it an IECLASS_NULL event)
  451.         moveq        #1,D0
  452. ChangeStatus    lea        Shifted(PC),A2
  453.         move.w        D0,(A2)
  454. * Just move on to next Event
  455. DontRemove    move.w        Shifted(PC),D0
  456.         beq.S        1$
  457.         ori.w        #IEQUALIFIER_LSHIFT,Qual(Event)    ; Set a SHIFT qualifier
  458. 1$        move.l        Next(Event),Event
  459.         bra.S        ieLoop
  460. * Lets return
  461. NoMoreEvents    move.l        EList,D0
  462.         Pop        Event/EList/A2
  463.         rts
  464. HandlerSize    =        *-IHS
  465. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  466. *»»» Input-handler end »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  467. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  468.  
  469. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  470. *»»» Data-definition start»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  471. *»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  472.  
  473. DosName        dc.b        'dos.library',0
  474. InputName    dc.b        'input.device',0
  475.         END
  476.  
  477.